﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using YJKGeometryFuncs;
using YJKCopyModel.YJKRevitWndr;
using YJKCopyModel.InteractiveOperation;

namespace YJKCopyModel.TransformWall
{
	public class WallManager
	{
		public static List<Curve> GetWallBorderCurves(List<ICadElement> lstCadElemInfo, string strWallLayer)
		{
			double val = AssistFunc.mmToFeet(1.0);
			List<Curve> list = new List<Curve>();
			foreach (ICadElement cadElement in lstCadElemInfo)
			{
				bool flag = cadElement is CurveInfo;
				if (flag)
				{
					CurveInfo curveInfo = cadElement as CurveInfo;
					bool flag2 = !curveInfo.ThisCurve.IsBound;
					if (!flag2)
					{
						bool flag3 = strWallLayer.CompareTo(curveInfo.UseLayerName) != 0;
						if (!flag3)
						{
							bool flag4 = Geometry.LessThan(curveInfo.ThisCurve.Length, val);
							if (!flag4)
							{
								Curve curve = WallManager.SetCurveElevation(curveInfo.ThisCurve, 0.0);
								bool flag5 = curve != null;
								if (flag5)
								{
									list.Add(curve);
								}
							}
						}
					}
				}
			}
			return list;
		}

		public static List<Curve> GetWindowBaseCurves(List<ICadElement> lstCadElemInfo, List<string> lstWindowLayer)
		{
			List<Curve> list = new List<Curve>();
			foreach (ICadElement cadElement in lstCadElemInfo)
			{
				bool flag = cadElement is DoorAndWindowBlockRefInfo;
				if (flag)
				{
					DoorAndWindowBlockRefInfo doorAndWindowBlockRefInfo = cadElement as DoorAndWindowBlockRefInfo;
					bool flag2 = lstWindowLayer.Contains(doorAndWindowBlockRefInfo.UseLayerName);
					if (flag2)
					{
						double num = AssistFunc.mmToFeet(doorAndWindowBlockRefInfo.UseScale.X);
						XYZ handDir = doorAndWindowBlockRefInfo.HandDir;
						XYZ useLocationPoint = doorAndWindowBlockRefInfo.UseLocationPoint;
						XYZ xyz = new XYZ(useLocationPoint.X, useLocationPoint.Y, 0.0);
						XYZ xyz2 = xyz - 0.5 * num * handDir;
						XYZ xyz3 = xyz + 0.5 * num * handDir;
						Line item = Line.CreateBound(xyz2, xyz3);
						list.Add(item);
					}
				}
			}
			return list;
		}

		public static ElementId GetWallType(Autodesk.Revit.DB.Document doc, string strWallType, string strUseage, double dWallCoreWidth)
		{
			bool flag = strWallType.CompareTo("<程序自选>") == 0;
			ElementId result;
			if (flag)
			{
				int num = Convert.ToInt32(AssistFunc.feetToMM(dWallCoreWidth));
				string text = (num > 200) ? "钢筋混凝土" : "砖";
				string arg = (strUseage.IndexOf("建") > -1) ? "建" : "结";
				string strNewWallType = string.Format("HY_{0}_{1}_{2}", arg, text, num.ToString());
				result = WallManager.CreateSingleStructWallType(doc, strNewWallType, text, dWallCoreWidth);
			}
			else
			{
				int num2 = strWallType.IndexOf(":");
				bool flag2 = num2 < 0;
				if (flag2)
				{
					result = ElementId.InvalidElementId;
				}
				else
				{
					string text2 = strWallType.Substring(0, num2);
					string text3 = strWallType.Substring(num2 + 1);
					bool flag3 = string.IsNullOrWhiteSpace(text2) || string.IsNullOrWhiteSpace(text3);
					if (flag3)
					{
						result = ElementId.InvalidElementId;
					}
					else
					{
						WallType wallType = WallManager.FindWallType(doc, text2, text3);
						bool flag4 = wallType == null;
						if (flag4)
						{
							result = ElementId.InvalidElementId;
						}
						else
						{
							bool flag5 = text2.CompareTo("幕墙") == 0 || text2.CompareTo("叠层墙") == 0;
							if (flag5)
							{
								result = wallType.Id;
							}
							else
							{
								bool flag6 = text2.CompareTo("基本墙") == 0;
								if (flag6)
								{
									double wallTypeCordWidth = WallManager.GetWallTypeCordWidth(wallType);
									bool flag7 = Geometry.IsEqual(wallTypeCordWidth, dWallCoreWidth);
									if (flag7)
									{
										result = wallType.Id;
									}
									else
									{
										string strNewWallType2 = text3 + "-" + Convert.ToInt32(AssistFunc.feetToMM(dWallCoreWidth)).ToString();
										result = WallManager.DuplicateWallType(doc, wallType, strNewWallType2, dWallCoreWidth);
									}
								}
								else
								{
									result = ElementId.InvalidElementId;
								}
							}
						}
					}
				}
			}
			return result;
		}

		public static Wall GetHostWall(Autodesk.Revit.DB.Document doc, XYZ ptPos, XYZ vcDir)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc, doc.ActiveView.Id);
			List<Element> list = filteredElementCollector.OfCategory(BuiltInCategory.OST_Walls).ToList<Element>();
			foreach (Element element in list)
			{
				Wall wall = element as Wall;
				bool flag = wall == null;
				if (!flag)
				{
					bool flag2 = !WallManager.IsPointInWall(ptPos, wall);
					if (!flag2)
					{
						LocationCurve locationCurve = wall.Location as LocationCurve;
						IntersectionResult intersectionResult = locationCurve.Curve.Project(ptPos);
						XYZ basisX = locationCurve.Curve.ComputeDerivatives(intersectionResult.Parameter, false).BasisX;
						bool flag3 = Geometry.IsParallel(basisX, vcDir);
						if (flag3)
						{
							return wall;
						}
					}
				}
			}
			return null;
		}

		private static bool IsPointInWall(XYZ pt, Wall wall)
		{
			LocationCurve locationCurve = wall.Location as LocationCurve;
			bool flag = locationCurve.Curve.GetType() == typeof(Line);
			bool result;
			if (flag)
			{
				result = WallManager.IsPointInLineWall(pt, wall);
			}
			else
			{
				bool flag2 = locationCurve.Curve.GetType() == typeof(Arc);
				result = (flag2 && WallManager.IsPointInArcWall(pt, wall));
			}
			return result;
		}

		private static bool IsPointInLineWall(XYZ pt, Wall wall)
		{
			LocationCurve locationCurve = wall.Location as LocationCurve;
			XYZ endPoint = locationCurve.Curve.GetEndPoint(0);
			XYZ endPoint2 = locationCurve.Curve.GetEndPoint(1);
			double val = wall.Width / 2.0;
			XYZ xyz = new XYZ(pt.X, pt.Y, endPoint.Z);
			XYZ xyz2 = Geometry.CalculateFootPoint(endPoint, endPoint2, xyz);
			double val2 = xyz.DistanceTo(xyz2);
			bool flag = Geometry.GreaterThan(val2, val);
			bool result;
			if (flag)
			{
				result = false;
			}
			else
			{
				bool flag2 = Geometry.IsEqual(xyz2, endPoint) || Geometry.IsEqual(xyz2, endPoint2);
				if (flag2)
				{
					result = false;
				}
				else
				{
					double num = xyz2.DistanceTo(endPoint);
					double num2 = xyz2.DistanceTo(endPoint2);
					double val3 = endPoint.DistanceTo(endPoint2);
					result = Geometry.IsEqual(num + num2, val3);
				}
			}
			return result;
		}

		private static bool IsPointInArcWall(XYZ pt, Wall wall)
		{
			LocationCurve locationCurve = wall.Location as LocationCurve;
			Arc arc = locationCurve.Curve as Arc;
			XYZ endPoint = arc.GetEndPoint(0);
			XYZ endPoint2 = arc.GetEndPoint(1);
			XYZ center = arc.Center;
			double val = wall.Width / 2.0;
			XYZ xyz = new XYZ(pt.X, pt.Y, center.Z);
			XYZ xyz2 = (xyz - center).Normalize();
			XYZ xyz3 = center + xyz2 * arc.Radius;
			double val2 = xyz.DistanceTo(xyz3);
			bool flag = Geometry.GreaterThan(val2, val);
			bool result;
			if (flag)
			{
				result = false;
			}
			else
			{
				bool flag2 = Geometry.IsEqual(xyz3, endPoint) || Geometry.IsEqual(xyz3, endPoint2);
				if (flag2)
				{
					result = false;
				}
				else
				{
					Line line = Line.CreateBound(center, xyz3);
                    result = ((int)arc.Intersect(line) == 8);
				}
			}
			return result;
		}

		private static ElementId DuplicateWallType(Autodesk.Revit.DB.Document doc, WallType resWallType, string strNewWallType, double dWallCoreWidth)
		{
			WallType wallType = WallManager.FindWallType(doc, "基本墙", strNewWallType);
			bool flag = wallType != null;
			ElementId result;
			if (flag)
			{
				result = wallType.Id;
			}
			else
			{
				ElementId elementId = ElementId.InvalidElementId;
				Transaction transaction = new Transaction(doc, "CreateWallType");
				transaction.Start();
				try
				{
					WallType wallType2 = resWallType.Duplicate(strNewWallType) as WallType;
					WallManager.SetWallTypeCordWidth(wallType2, dWallCoreWidth);
					elementId = wallType2.Id;
					transaction.Commit();
				}
				catch
				{
					transaction.RollBack();
				}
				result = elementId;
			}
			return result;
		}

		private static ElementId CreateSingleStructWallType(Autodesk.Revit.DB.Document doc, string strNewWallType, string strMaterialName, double dWallCoreWidth)
		{
			WallType wallType = WallManager.FindWallType(doc, "基本墙", strNewWallType);
			bool flag = wallType != null;
			ElementId result;
			if (flag)
			{
				result = wallType.Id;
			}
			else
			{
				ElementId elementId = ElementId.InvalidElementId;
				Transaction transaction = new Transaction(doc, "CreateWallType");
				transaction.Start();
				try
				{
					WallType wallType2 = WallManager.FindWallType(doc, "基本墙", null);
					WallType wallType3 = wallType2.Duplicate(strNewWallType) as WallType;
					elementId = wallType3.Id;
					double num = AssistFunc.mmToFeet(3000.0);
                    MaterialFunctionAssignment materialFunctionAssignment = (MaterialFunctionAssignment)1;
					ElementId materialId = WallManager.GetMaterialId(doc, strMaterialName);
					CompoundStructure compoundStructure = CompoundStructure.CreateSingleLayerCompoundStructure(num, materialFunctionAssignment, dWallCoreWidth, materialId);
					compoundStructure.StructuralMaterialIndex = 0;
					wallType3.SetCompoundStructure(compoundStructure);
					transaction.Commit();
				}
				catch
				{
					transaction.RollBack();
				}
				result = elementId;
			}
			return result;
		}

		private static WallType FindWallType(Autodesk.Revit.DB.Document doc, string strWallFamily, string strWallSymbol = null)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			IList<Element> list = filteredElementCollector.OfClass(typeof(WallType)).ToElements();
			foreach (Element element in list)
			{
				WallType wallType = element as WallType;
				bool flag = wallType == null || wallType.FamilyName.CompareTo(strWallFamily) != 0;
				if (!flag)
				{
					bool flag2 = string.IsNullOrWhiteSpace(strWallSymbol);
					if (flag2)
					{
						return wallType;
					}
					bool flag3 = wallType.Name.CompareTo(strWallSymbol) == 0;
					if (flag3)
					{
						return wallType;
					}
				}
			}
			return null;
		}

		private static ElementId GetMaterialId(Autodesk.Revit.DB.Document doc, string strMaterialName)
		{
			ElementId result = ElementId.InvalidElementId;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			ICollection<Element> collection = filteredElementCollector.OfClass(typeof(Material)).ToElements();
			foreach (Element element in collection)
			{
				Material material = element as Material;
				bool flag = material.Name.CompareTo(strMaterialName) == 0;
				if (flag)
				{
					result = material.Id;
					break;
				}
			}
			return result;
		}

		private static Curve SetCurveElevation(Curve thisCurve, double dElevation)
		{
			XYZ endPoint = thisCurve.GetEndPoint(0);
			XYZ endPoint2 = thisCurve.GetEndPoint(1);
			XYZ xyz = new XYZ(endPoint.X, endPoint.Y, dElevation);
			XYZ xyz2 = new XYZ(endPoint2.X, endPoint2.Y, dElevation);
			bool flag = thisCurve is Line;
			Curve result;
			if (flag)
			{
				result = Line.CreateBound(xyz, xyz2);
			}
			else
			{
				bool flag2 = thisCurve is Arc;
				if (flag2)
				{
					XYZ xyz3 = thisCurve.Evaluate(0.5, true);
					XYZ xyz4 = new XYZ(xyz3.X, xyz3.Y, dElevation);
					result = Arc.Create(xyz, xyz2, xyz4);
				}
				else
				{
					result = null;
				}
			}
			return result;
		}

		private static void SetWallTypeCordWidth(WallType type, double dCoreWidth)
		{
			CompoundStructure compoundStructure = type.GetCompoundStructure();
			int num = compoundStructure.StructuralMaterialIndex;
			bool flag = num < 0;
			if (flag)
			{
				double val = 0.0;
				int firstCoreLayerIndex = compoundStructure.GetFirstCoreLayerIndex();
				int lastCoreLayerIndex = compoundStructure.GetLastCoreLayerIndex();
				IList<CompoundStructureLayer> layers = compoundStructure.GetLayers();
				for (int i = firstCoreLayerIndex; i <= lastCoreLayerIndex; i++)
				{
					CompoundStructureLayer compoundStructureLayer = layers[i];
                    bool flag2 = (int)compoundStructureLayer.Function != 1;
					if (!flag2)
					{
						bool flag3 = Geometry.LessThan(val, compoundStructureLayer.Width);
						if (flag3)
						{
							num = i;
							val = compoundStructureLayer.Width;
						}
					}
				}
				bool flag4 = num < 0;
				if (flag4)
				{
					val = 0.0;
					for (int j = firstCoreLayerIndex; j <= lastCoreLayerIndex; j++)
					{
						CompoundStructureLayer compoundStructureLayer2 = layers[j];
						bool flag5 = Geometry.LessThan(val, compoundStructureLayer2.Width);
						if (flag5)
						{
							num = j;
							val = compoundStructureLayer2.Width;
						}
					}
				}
			}
			bool flag6 = num >= 0;
			if (flag6)
			{
				compoundStructure.StructuralMaterialIndex = num;
				compoundStructure.SetLayerWidth(num, dCoreWidth);
			}
			type.SetCompoundStructure(compoundStructure);
		}

		private static double GetWallTypeCordWidth(WallType type)
		{
			double num = 0.0;
			CompoundStructure compoundStructure = type.GetCompoundStructure();
			int firstCoreLayerIndex = compoundStructure.GetFirstCoreLayerIndex();
			int lastCoreLayerIndex = compoundStructure.GetLastCoreLayerIndex();
			IList<CompoundStructureLayer> layers = compoundStructure.GetLayers();
			for (int i = firstCoreLayerIndex; i <= lastCoreLayerIndex; i++)
			{
				num += layers[i].Width;
			}
			return num;
		}

		public const string BasicWallFamily = "基本墙";

		public const string CurtainWallFamily = "幕墙";

		public const string LaminatedWallFamily = "叠层墙";
	}
}
